#include <QPointF>
#include <QDebug>
#include <Qstandarditemmodel>
#include <QMessageBox>
#include <QTableWidget>
#include <QInputDialog>
#include <QColorDialog>
#include <QTime>
#include <QSet>

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myline.h"
#include "myvex.h"

MainWindow::MainWindow(QWidget *parent):
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    this->setWindowIcon(QIcon(":/ActionIcons/res/window.png"));
    ui->setupUi(this);
    pr = new PageRank(this);
    scene = new QGraphicsScene(this); //创建QGraphicsScene
    ui->view->setScene(scene); //与view关联
    ui->view->setCursor(Qt::CrossCursor); //设置鼠标
    ui->view->setDragMode(QGraphicsView::RubberBandDrag);

    itemMenu = new QMenu();
    itemMenu_v = new QMenu();
    itemMenuE = new QMenu();
    itemMenu->addAction(ui->actionAddE);
    itemMenu->addAction(ui->actionDele);
    itemMenu->addAction(ui->actionColor);
    itemMenu->addAction(ui->actionName);
    itemMenu_v->addAction(ui->actionSet);
    itemMenu_v->addAction(ui->actionCancel);
    itemMenuE->addAction(ui->actionDele);
    itemMenuE->addAction(ui->actionColor);

    connect(ui->actionAddV,&QAction::triggered,this,&on_actAddV_triggered);
    connect(ui->actionAddE2,&QAction::triggered,this,&on_actAddE2_triggered);
    connect(ui->actionAddE,&QAction::triggered,this,&on_actAddE_triggered);
    connect(ui->actionCancel,&QAction::triggered,this,&on_actCancel_triggered);
    connect(ui->actionSet,&QAction::triggered,this,&on_actSet_triggered);
    connect(ui->actionColor,&QAction::triggered,this,&on_actColor_triggered);
    connect(ui->actionName,&QAction::triggered,this,&on_actName_triggered);

    connect(ui->actionNew,&QAction::triggered,this,&on_actNew_triggered);//新建
    connect(ui->actionClose,&QAction::triggered,this,&on_actClose_triggered);
    connect(ui->actionExit,&QAction::triggered,this,&on_actExit_triggered);
    connect(ui->actionRun,&QAction::triggered,this,&on_actRun_triggered);
    connect(ui->actionDele,&QAction::triggered,this,&on_actDel_triggered);

    connect(ui->actionMatrix,&QAction::triggered,this,&on_actMatrix_triggered);
    connect(ui->actionRand,&QAction::triggered,this,&on_actRand_triggered);
    connect(ui->actionShowIO,&QAction::triggered,this,&on_actShowIO_triggered);
    connect(ui->actionShowVN,&QAction::triggered,this,&on_actShowVN_triggered);
    connect(ui->actionShowVO,&QAction::triggered,this,&on_actShowVO_triggered);

    ui->outputWidget->setVisible(false);
    ui->matWidget->setVisible(false);
    setCloseMode(true);

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::setCloseMode(bool y,bool v)
{
    ui->view->setDisabled(y && v);
    ui->menuEdit->setDisabled(y);
    ui->menuTools->setDisabled(y);
    ui->mainToolBar->setDisabled(y);
    ui->actionNew->setDisabled(!y || !v);
    ui->actionClose->setDisabled(y && v);
}

void MainWindow::on_actAddE_triggered()
{
    MyVex *p2 = new MyVex(pr->totalVex+1,this->itemMenu_v);
    p2->setVirtual();
    p2->setPos(ui->view->mapToScene(mapFromGlobal(QCursor::pos())));
    scene->addItem(p2);
    MyLine *l = new MyLine((MyVex*)(scene->selectedItems()[0]),p2);
    l->setVirtual();
    scene->addItem(l);
    scene->clearSelection();
    p2->setSelected(true);
    setCloseMode(true,false);
}

void MainWindow::on_actSet_triggered()
{
    MyVex * curV = (MyVex*)(scene->selectedItems()[0]);
    QPointF itemPos = curV->pos()+QPointF(12.5,12.5);
    QList<QGraphicsItem*> items = scene->items(itemPos,Qt::IntersectsItemShape);
    for(int i = 2;i<items.size();i++){
        if(items[i]->type() == QGraphicsEllipseItem::Type){
            MyVex * startV = curV->inlines[0]->s;
            MyVex *endV = (MyVex*)(items[i]);
            int i = startV->index;
            int j = endV->index;//qDebug()<<"i = "<<i<<"j = "<<j;
            if(i == j) break;
            else if(pr->AdjMatrix[i][j]==0){
                on_actCancel_triggered();
                pr->AdjMatrix[i][j] = 1;
                MyLine *e = new MyLine(startV,endV,itemMenuE);
                scene->addItem(e);
                ui->view->eList.append(e);
                setCloseMode(false);
                return ;
            }

        }
    }
    int i = curV->inlines[0]->s->index;
    curV->setSolid();
    curV->inlines[0]->setSolid();
    curV->itemMenu = itemMenu;
    curV->index = pr->VexNum;
    curV->inlines[0]->itemMenu = itemMenuE;
    pr->VexNum++;
    pr->totalVex++;
    pr->SetVex(pr->VexNum);
    pr->AdjMatrix[i][curV->index] = 1;
    ui->view->vList.append(curV);
    ui->view->eList.append(curV->inlines[0]);
    setCloseMode(false);
}

void MainWindow::on_actCancel_triggered()
{
    MyVex * curV = (MyVex*)(scene->selectedItems()[0]);
    delete curV;qDebug()  << "delete";
    setCloseMode(false);
}

void MainWindow::on_actColor_triggered()
{
    if(scene->selectedItems().size()!=0){
        QGraphicsItem * item = scene->selectedItems()[0];
        if(item->type()==QGraphicsEllipseItem::Type){
            QColor color = QColorDialog::getColor(((MyVex*)item)->brush->color(),this,"选择顶点颜色");
            if(color.isValid()) ((MyVex*)item)->brush->setColor(color);
            ((MyVex*)item)->setBrush(*(((MyVex*)item)->brush));
        }
        else{
            QColor color = QColorDialog::getColor(((MyLine*)item)->pen->color(),this,"选择直线颜色");
            if(color.isValid()) ((MyLine*)item)->pen->setColor(color);
            ((MyLine*)item)->setPen(*(((MyLine*)item)->pen));
            ((MyLine*)item)->arrow_1->setPen(*(((MyLine*)item)->pen));
            ((MyLine*)item)->arrow_2->setPen(*(((MyLine*)item)->pen));
        }
    }

}

void MainWindow::on_actName_triggered()
{
    //qgraphicsitem * item = scene->selectedItems()[0];
    if(scene->selectedItems().size()!=1||scene->selectedItems()[0]->type()!=QGraphicsEllipseItem::Type){
        bool ok;
        QRegExp rx("[ 0-9]+ [^ ]");
        QString s = QInputDialog::getText(this,"命名","输入顶点编号并命名",QLineEdit::Normal,"",&ok);
        if(ok){
            if(s.contains(rx)){
                int Vno = s.split(" ").at(0).toInt();
                for(MyVex* v:ui->view->vList){
                    if(v->Vno == Vno){
                        v->info = ": "+s.split(" ").at(1);
                        v->showInfo(true);
                        return;
                    }
                }
            }
            else{
                QMessageBox::warning(this,"提示","格式错误：编号+空格+命名（不含空格）");
                return ;
            }
        }
     }
    else{
        MyVex * item = (MyVex*)(scene->selectedItems()[0]);
        bool ok;
        QRegExp rx("[^ ]+");
        QString s = QInputDialog::getText(this,"命名","输入",QLineEdit::Normal,"",&ok);
        if(ok){
            if(s.contains(rx)){
                item->info = ": "+s;
                item->showInfo(true);
            }
            else{
                QMessageBox::warning(this,"提示","命名不能含空格");
                return ;
            }
        }
    }
}

void MainWindow::on_actMatrix_triggered()
{
    ui->Adjmat->clear();
    ui->Adjmat->setRowCount(pr->VexNum);
    ui->Adjmat->setColumnCount(pr->VexNum);
    QStringList sl;
    for(int i = 0;i<pr->VexNum;i++){
        sl.append(QString::number(ui->view->vList[i]->Vno));
        ui->Adjmat->setColumnWidth(i,40);
    }
    ui->Adjmat->setHorizontalHeaderLabels(sl);
    ui->Adjmat->setVerticalHeaderLabels(sl);
    for(int i = 0;i<pr->VexNum;i++){
        for(int j = 0;j<pr->VexNum;j++){
           ui->Adjmat->setItem(i,j,new QTableWidgetItem(" "+QString::number(pr->AdjMatrix[i][j])));
        }
    }
    ui->matWidget->show();
}

void MainWindow::on_actShowIO_triggered()
{
    ui->Adjmat->clear();
    ui->Adjmat->setRowCount(pr->VexNum);
    ui->Adjmat->setColumnCount(3);
    QStringList sl ;
    sl << "编号" << "出度" << "入度" ;
    ui->Adjmat->setHorizontalHeaderLabels(sl);
    ui->Adjmat->setColumnWidth(0,40);
    ui->Adjmat->setColumnWidth(1,40);
    ui->Adjmat->setColumnWidth(2,40);
    for(int i = 0;i<pr->VexNum;i++){
        ui->Adjmat->setItem(i,0,new QTableWidgetItem(QString::number(ui->view->vList[i]->Vno)));
        ui->Adjmat->setItem(i,1,new QTableWidgetItem(QString::number(ui->view->vList[i]->outlines.size())));
        ui->Adjmat->setItem(i,2,new QTableWidgetItem(QString::number(ui->view->vList[i]->inlines.size())));
    }
    ui->matWidget->show();
}

void MainWindow::on_actShowVN_triggered()
{
    for(int i = 0;i<ui->view->vList.size();i++){
        ui->view->vList[i]->showInfo(true);
    }
    ui->actionShowVN->setDisabled(true);
    ui->actionShowVO->setDisabled(false);
}

void MainWindow::on_actShowVO_triggered()
{
    for(int i = 0;i<ui->view->vList.size();i++){
        ui->view->vList[i]->showInfo(false);
    }
    ui->actionShowVO->setDisabled(true);
    ui->actionShowVN->setDisabled(false);
}

void MainWindow::on_actNew_triggered()
{
    pr->totalVex = pr->VexNum = 6;
    pr->SetVex(pr->VexNum);
    for(int i = 0;i<2;i++){
        for(int j = 0;j<3;j++){
            MyVex *v= new MyVex(i*3+j+1,this->itemMenu);
            v->setPos(-100*(j%2)+i*100*(1+j%2*2),100*j);
            scene->addItem(v);
            ui->view->vList.append(v);
        }
    }
    newdlg = new Newactdlg(this);
    connect(newdlg,&Newactdlg::CheckAt,pr,&PageRank::SwicthAt);
    newdlg->exec();
    for(int i = 0;i<pr->AdjMatrix.size();i++){
        for(int j = 0;j < pr->AdjMatrix[i].size();j++){
            if(pr->AdjMatrix[i][j]==1){
                MyLine *e = new MyLine(ui->view->vList.at(i),ui->view->vList.at(j),itemMenuE);
                scene->addItem(e);
                ui->view->eList.append(e);
            }
        }
    }
//    ui->actionNew->setDisabled(true);
//    ui->actionClose->setDisabled(false);
    setCloseMode(false);
   // ui->out
}

void MainWindow::on_actClose_triggered()
{
    scene->clear();
    pr->SetVex(0);
    ui->view->vList.clear();
    ui->view->eList.clear();
    setCloseMode(true);
    ui->outputWidget->setVisible(false);
    ui->matWidget->setVisible(false);
}

void MainWindow::on_actExit_triggered()
{
    this->close();
}

void MainWindow::on_actRun_triggered()
{
    //判断
    if(ui->view->vList.size()<6 || ui->view->isSL()){
        QMessageBox::warning(this,"提示","顶点数不能少于6，且不能存\n在出度或入度为0的顶点");
        return ;
    }
    pr->Rank();//qDebug()<<"run";
//    if(i == 0){
//        QMessageBox::warning(this,"警告","迭代超过2000次未收\n敛,请尝试更改连线");
//    }
    QStandardItemModel *model = new QStandardItemModel(pr->VexNum,2);
    model->setHeaderData(0,Qt::Horizontal,"顶点编号");
    model->setHeaderData(1,Qt::Horizontal,"PR值");
    for(int i = 0;i<model->rowCount();i++){
        model->setItem(i,0,new QStandardItem("          "+QString::number(ui->view->vList[i]->Vno)));
        model->setItem(i,1,new QStandardItem("      "+QString::number(pr->prValue[i])));
    }
    QItemSelectionModel *m = ui->out->selectionModel();
    delete m;
    ui->out->setModel(model);
    ui->out->horizontalHeader()->setSortIndicator(0,Qt::AscendingOrder);
    ui->out->horizontalHeader()->setSortIndicatorShown(true);
    ui->outputWidget->show();
    connect(ui->out->horizontalHeader(),&QHeaderView::sectionClicked,[=](int c){
        model->sort(c,ui->out->horizontalHeader()->sortIndicatorOrder());
    });
}

void MainWindow::on_actDel_triggered()
{
    QList<QGraphicsItem*> selected = scene->selectedItems();
    if(selected.size()==0){
        QMessageBox::warning(this,"提示","未选中任何内容");
        return ;
    }
    for(int i = 0;i < selected.size();i++){
        if(selected[i]->type()==QGraphicsLineItem::Type){//删边
            MyLine * l = (MyLine*)selected[i];
            pr->AdjMatrix[l->s->index][l->e->index] = 0;
            delete selected[i];
            selected.removeAt(i--);
        }
    }
    while(selected.size()>0){//删顶点
        MyVex * v = (MyVex*)(selected.first());
        pr->SetVex(pr->VexNum-1,v->index);
        ui->view->updateIndex(v->index);
        delete v;
        selected.removeFirst();
    }
}

void MainWindow::on_actAddV_triggered()
{
    bool ok;
    int num = QInputDialog::getInt(this,"添加顶点","输入添加顶点个数",3,0,100,1,&ok);
    if(ok){
        pr->SetVex(pr->VexNum+num);
        for(int i = 0;i<num;i++){
            MyVex * v = new MyVex(++(pr->totalVex),itemMenu);
            v->index = pr->VexNum-num+i;
            v->setPos(-100+50*(i%10),50*(i/10+5));
            ui->view->vList.append(v);
            scene->addItem(v);
        }
    }
}

void MainWindow::on_actAddE2_triggered()
{
    QList<QGraphicsItem*> li = scene->selectedItems();
    if(li.size()!=1 || li[0]->type()!=QGraphicsEllipseItem::Type){
        QMessageBox::warning(this,"提示","先选中一个顶点");
        return ;
    }
    bool ok;
    QString s = QInputDialog::getText(this,"添加边","输入编号",QLineEdit::Normal,"",&ok);
    if(ok){
       QRegExp rx("[ 0-9]+[ ]+[io]");
       if(s.contains(rx) == false){
           QMessageBox::warning(this,"提示","输入格式：编号+空格+i/o(入或出)");
           return ;
       }
       MyVex * curV = (MyVex *)li[0];
       QList<QString> sl = s.split(" ");
       bool in = sl.last() == "i";
       sl.removeLast();
       while(sl.size()>0){
           int Vno = sl.last().toInt();
           for(int i = 0;i<ui->view->vList.size();i++){
               if(ui->view->vList[i]->Vno==Vno&&curV->Vno!=Vno){
                   MyLine * l;
                   MyVex *v = ui->view->vList[i];
                   if(in&&pr->AdjMatrix[v->index][curV->index]==0){
                       l = new MyLine(ui->view->vList[i],curV,itemMenuE);
                       pr->AdjMatrix[v->index][curV->index] = 1;
                   }
                   else if(!in&&pr->AdjMatrix[curV->index][v->index]==0){
                       l = new MyLine(curV,ui->view->vList[i],itemMenuE);
                       pr->AdjMatrix[curV->index][v->index] = 1;
                   }
                   scene->addItem(l);
               }
           }
           sl.removeLast();
       }
    }
}

void MainWindow::on_actRand_triggered()
{
    if(ui->view->vList.size() < 2) return ;
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
    for(MyVex * v : ui->view->vList){
        if(v->outlines.size()==0){
            int rn = 1+qrand()%(pr->VexNum-1);
            QSet<int> set;
            while(set.size()<rn){
                int r = qrand()%(pr->VexNum);
                if(r != v->index) set.insert(r);
            }
            for(int i : set.toList()){
                MyLine * l = new MyLine(v,ui->view->vList[i],itemMenuE);
                scene->addItem(l);
                pr->AdjMatrix[v->index][ui->view->vList[i]->index] = 1;
            }
        }
        if(v->inlines.size()==0){
            int rn = 1+qrand()%(pr->VexNum-1);
            QSet<int> set;
            while(set.size()<rn){
                int r = qrand()%(pr->VexNum);
                if(r != v->index) set.insert(r);
            }
            for(int i : set.toList()){
                MyLine * l = new MyLine(ui->view->vList[i],v,itemMenuE);
                scene->addItem(l);
                pr->AdjMatrix[ui->view->vList[i]->index][v->index] = 1;
            }
        }
    }
}
